import { Matcher } from "..";

export default class ChineseMatcher implements Matcher {

    public readonly regex = /(?:\/\*(?:[\s\S]*?)\*\/|\/\/.*|<!--[\s\S]*?-->|"""\s*[\s\S]*?\s*"""|'''\s*[\s\S]*?\s*''')|([\u4e00-\u9fa5](?:[\u4e00-\u9fa5\p{P}\s\d\-_•·。，、；：？！（）【】\[\]\{\}《》']*[\u4e00-\u9fa5])?|[\u4e00-\u9fa5](?:[\u4e00-\u9fa5\p{P}\s\d\-_•·。，、；：？！（）【】\[\]\{\}《》"]*[\u4e00-\u9fa5])?)/gu;
    private readonly quoteRegex = /"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`/g;
    
    public readonly name = "中文字符";
    public readonly id = crypto.randomUUID();

    match(content: string): Array<string> {
        let result: Array<string> = [];
        
        // 移除模板中注释, style标签及style属性
        const cleaned = content.replace(/\/\*[\s\S]*?\*\//g, '').replace(/\/\/.*$/gm, '')
            .replace(/<!--[\s\S]*?-->/g, '').replace(/"""\s*[\s\S]*?\s*"""/g, '')
            .replace(/'''\s*[\s\S]*?\s*'''/g, '')
            .replace(/<style[\s\S]*?<\/style>/gi, '')
            .replace(/style\s*=\s*["'`][^"'`]*["'`]/g, '');

        const fnRegex = /[a-zA-Z_$][a-zA-Z0-9_$.]*\s*\(\s*["'`]((?:[^"'`\\]|\\.)*?)["'`]/g;
        let match;
        const fnRanges: Array<{ start: number; end: number }> = [];

        fnRegex.lastIndex = 0;
        while ((match = fnRegex.exec(cleaned)) !== null) {
            const text = match[1];
            
            if (/[\u4e00-\u9fff]/.test(text) && !result.includes(text)) {
                result.push(text);
            }
            
            fnRanges.push({ start: match.index, end: match.index + match[0].length });
        }

        this.quoteRegex.lastIndex = 0;
        while ((match = this.quoteRegex.exec(cleaned)) !== null) {
            const quotedString = match[0];
            const text = quotedString.slice(1, -1);
            const isFn = fnRanges.some(range => match.index >= range.start && match.index < range.end);
            const isExist = result.some(item => text.includes(item));
            if (!isFn && !isExist && /[\u4e00-\u9fff]/.test(text) && !result.includes(text)) {
                result.push(text);
            }
        }

        return result;
    }

    replace(template: string, data: Record<string, string>){
        return template.replace(this.regex, (match, p1) => {
            if (!p1) return match;
            const replacement = data[p1] || p1;
            return match.replace(p1, replacement);
        });
    }
}